package sk.jp.commons.utils.xml;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Utility class for XPath processing.
 *
 * @author Jan Pastor 
 */
public class XPathUtils {

    private XPathUtils() {
    }

    //----------------------------------------------------------------------

    /**
     * Return a node selected by given <code>xPath</code> or null if
     * node not found.
     * @param contextNode the node to start searching from.
     * @param xPath a valid XPath expression.
     * @return the first node found that matches the XPath, or null.
     * @throws XPathExpressionException if select node failed.
     */
    public static Node getNode(Node contextNode, String xPath)
                            throws XPathExpressionException {
        XPath xp = XPathFactory.newInstance().newXPath();
        return (Node) xp.evaluate(xPath, contextNode, XPathConstants.NODE);
    }

    /**
     * Return a node selected by given <code>xPath</code> or throw exception if
     * node not found.
     * @param contextNode the node to start searching from.
     * @param xPath a valid XPath v.
     * @return the first node found that matches the XPath.
     * @throws XPathExpressionException if evaluate xPath expression failed.
     * @throws IllegalArgumentException if node not found.
     */
    public static Node getRequiredNode(Node contextNode, String xPath)
                                    throws XPathExpressionException {
        Node node = getNode(contextNode, xPath);
        if(node == null){
            throw new IllegalArgumentException("Required node not found (context node: '" +
                                               contextNode.getNodeName() +
                                               "', XPath expression: '" +xPath + "')");
        }
        return node;
    }

    /**
     * Return a nodelist selected by given <code>xPath</code>.
     * @param contextNode the node to start searching from.
     * @param xPath a valid XPath expression.
     * @return a list of selected nodes.
     * @throws XPathExpressionException if select nodes fails.
     */
    public static NodeList getNodeIterator(Node contextNode, String xPath)
                                            throws XPathExpressionException {
        XPath xp = XPathFactory.newInstance().newXPath();
        return (NodeList) xp.evaluate(xPath, contextNode, XPathConstants.NODESET);
    }

    /**
     *
     * @param contextNode the node to start searching from.
     * @param xPath a valid XPath expression.
     * @return evaluation result.
     * @throws XPathExpressionException if evaluate XPath expression fails.
     */
    public static boolean evalBoolean(Node contextNode, String xPath)
                                    throws XPathExpressionException {
        XPath xp = XPathFactory.newInstance().newXPath();
        Boolean r = (Boolean) xp.evaluate(xPath, contextNode, XPathConstants.BOOLEAN);
        return r.booleanValue();
    }

}
